﻿#region Copyright
//***************************************************************************************
//                              This module is part of the 
//                                  GreenPoint Package
//                                     developeb by
//                                      Green Team
//***************************************************************************************
//
//   PROJECT NAME:    GreenTeam.SharePoint.
//   AUTHOR:          Claudio Brotto.
//   CONTACTS:        mailto: cbrotto@greenteam.it
//                    www.greenteam.it
//   REFERENCES:      n/a.
//
//=======================================================================================
//
//   HISTORY: 
//   --------
//    
//   --------------------------------------------------------------------------------
//  |  #  |   Date   |    Author    |                   Reason                       |
//  |-----|----------|--------------|------------------------------------------------|
//  |  1  | --/--/-- | C. Brotto    | Original release.                              |
//   --------------------------------------------------------------------------------
//
//=======================================================================================
//
//   LICENSE (Microsoft Public License - Ms-PL)
//   ------------------------------------------
// 
// This license governs use of the accompanying software. If you use the software, you 
// accept this license. If you do not accept the license, do not use the software.
// 1. Definitions
// The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have 
// the same meaning here as under U.S. copyright law.
// A “contribution” is the original software, or any additions or changes to the 
// software.
// A “contributor” is any person that distributes its contribution under this license.
// “Licensed patents” are a contributor’s patent claims that read directly on its 
// contribution.
// 
// 2. Grant of Rights
// (A) Copyright Grant- Subject to the terms of this license, including the license 
// conditions and limitations in section 3, each contributor grants you a non-exclusive, 
// worldwide, royalty-free copyright license to reproduce its contribution, 
// prepare derivative works of its contribution, and distribute its contribution or any 
// derivative works that you create.
// (B) Patent Grant- Subject to the terms of this license, including the license 
// conditions and limitations in section 3, each contributor grants you a non-exclusive, 
// worldwide, royalty-free license under its licensed patents to make, have made, use, 
// sell, offer for sale, import, and/or otherwise dispose of its contribution in the 
// software or derivative works of the contribution in the software.
// 
// 3. Conditions and Limitations
// (A) No Trademark License- This license does not grant you rights to use any 
// contributors’ name, logo, or trademarks.
// (B) If you bring a patent claim against any contributor over patents that you claim 
// are infringed by the software, your patent license from such contributor to the 
// software ends automatically.
// (C) If you distribute any portion of the software, you must retain all copyright, 
// patent, trademark, and attribution notices that are present in the software.
// (D) If you distribute any portion of the software in source code form, you may do so 
// only under this license by including a complete copy of this license with your 
// distribution. If you distribute any portion of the software in compiled or object code 
// form, you may only do so under a license that complies with this license.
// (E) The software is licensed “as-is.” You bear the risk of using it. The contributors 
// give no express warranties, guarantees or conditions. You may have additional consumer 
// rights under your local laws which this license cannot change. To the extent permitted 
// under your local laws, the contributors exclude the implied warranties of 
// merchantability, fitness for a particular purpose and non-infringement.
// 
//***************************************************************************************
#endregion

#region Code
namespace GreenPoint.CustomFields
{
  #region using Directives
  using Microsoft.SharePoint;
  using Microsoft.SharePoint.WebControls;
  using System;
  using System.Collections.Generic;
  #endregion

  #region Coordinates Field Value Class
  /// <summary>
  /// The data structure that holds latitude and longitude information.
  /// </summary>
  public class CoordinatesFieldValue : SPFieldMultiColumnValue
  {
    #region Constants
    /// <summary>
    /// The number of subfields for the multicolumn field value type.
    /// </summary>
    private const Int32 COLUMNS_NUMBER = 2;

    /// <summary>
    /// The index of the latitude field in the multicolumn field value type.
    /// </summary>
    private const Int32 LATITUDE_FIELD_INDEX = 0;

    /// <summary>
    /// The index of the longitude field in the multicolumn field value type.
    /// </summary>
    private const Int32 LONGITUDE_FIELD_INDEX = 1;
    #endregion

    #region Properties
    /// <summary>
    /// An invalid coordinate value.
    /// </summary>
    public static readonly Double InvalidCoordinate = Double.NaN;

    /// <summary>
    /// The latitude value.
    /// </summary>
    public Double Latitude
    {
      get
      {
        return ParseCoordinate(base[LATITUDE_FIELD_INDEX]);
      }
      set
      {
        base[LATITUDE_FIELD_INDEX] = value.ToString();
      }
    }

    /// <summary>
    /// The longitude value.
    /// </summary>
    public Double Longitude
    {
      get
      {
        return ParseCoordinate(base[LONGITUDE_FIELD_INDEX]);
      }
      set
      {
        base[LONGITUDE_FIELD_INDEX] = value.ToString();
      }
    }
    #endregion

    #region Constructors
    /// <summary>
    /// Creates instances of the Coordinates Field Value type.
    /// </summary>
    public CoordinatesFieldValue()
      : base(COLUMNS_NUMBER)
    {
    }

    /// <summary>
    /// Creates instances of the Coordinates Field Value type.
    /// </summary>
    /// <param name="fieldValue"></param>
    public CoordinatesFieldValue(String fieldValue)
      : base(fieldValue)
    {
    }
    #endregion

    #region Validation
    /// <summary>
    /// Ensure valid values are available for both latitude and longitude.
    /// </summary>
    /// <returns></returns>
    public Boolean IsValid()
    {
      // Use static method in System.Double to check for NaN.
      // Direct comparison against CoordinatesField.InvalidCoordinate does not produce correct results.
      return !Double.IsNaN(this.Latitude) && !Double.IsNaN(this.Longitude);
    } 
    #endregion

    #region Helpers
    /// <summary>
    /// Converts a string representation of a coordinate into its floating point representation.
    /// </summary>
    /// <param name="coordinateText"></param>
    /// <returns></returns>
    internal static Double ParseCoordinate(String coordinateText)
    {
      Double coordinate;
      if (!Double.TryParse(coordinateText, out coordinate))
      {
        coordinate = CoordinatesFieldValue.InvalidCoordinate;
      }
      return coordinate;
    }

    /// <summary>
    /// Factory method, creates instances of the Coordinates Field Value type, based upon latitude and longitude values.
    /// </summary>
    /// <param name="latitude"></param>
    /// <param name="longitude"
    /// <returns></returns>
    internal static CoordinatesFieldValue Parse(String latitude, String longitude)
    {
      // Check for empty values.
      if (String.IsNullOrEmpty(latitude) && String.IsNullOrEmpty(longitude))
      {
        return null;
      }

      // Return a strongly typed value.
      CoordinatesFieldValue value = new CoordinatesFieldValue();
      value.Latitude = ParseCoordinate(latitude);
      value.Longitude = ParseCoordinate(longitude);
      return value;
    }
    #endregion
  }
  #endregion
}
#endregion
